package tech.yixiyun.framework.kuafu.controller.route;


import tech.yixiyun.framework.kuafu.controller.PathResolver;
import tech.yixiyun.framework.kuafu.controller.annotation.Controller;
import tech.yixiyun.framework.kuafu.controller.annotation.Route;
import tech.yixiyun.framework.kuafu.log.LOGGER;
import tech.yixiyun.framework.kuafu.view.View;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 路由全局上下文
 */
public class RouteContext {

    /**
     * 根节点
     */
    private static final ConcurrentHashMap<String, RouteNode> ROUTE_MAP = new ConcurrentHashMap<>(200);




    /**
     * 注册路由
     * @param fullPath
     * @param method
     */
    public static void register(String fullPath, Method method) {
        RouteNode route = new RouteNode(fullPath, method);

        route = ROUTE_MAP.putIfAbsent(fullPath, route);
        if (route != null) {
            throw new RuntimeException("【" + fullPath + "】已注册过路由，关联：" + method + ", 本次注册失败");
        }
    }

    /**
     * 注册一个Controller类的所有路由
     * @param controllerClass
     */
    public static void register(Class controllerClass) {
        Controller controller = (Controller) controllerClass.getAnnotation(Controller.class);
        if (controller == null) {
            LOGGER.warn("{}不是Controller类无法注册路由", controllerClass.getName());
        }
        if (controller != null) {

            String basePath = PathResolver.resolve(controllerClass.getSimpleName(), controller.value());

            Method[] methods = controllerClass.getDeclaredMethods();
            for (Method method : methods) {
                int modifiers = method.getModifiers();
                if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers) == false && View.class.isAssignableFrom(method.getReturnType())) {
                    String fullPath = basePath ;
                    Route route = method.getAnnotation(Route.class);
                    if (route != null) {
                        fullPath = route.value();
                    } else {
                        fullPath += "/" + method.getName();
                    }
                    if (fullPath.startsWith("/") == false) {
                        fullPath = "/" + fullPath;
                    }
                    LOGGER.trace("Route注册：" + fullPath + "  " + method.getDeclaringClass().getName()+":"+method.getName()+"()");

                    register(fullPath, method);

                }
            }

        }
    }




    /**
     * 获取Route对应的Method
     * @param uri
     * @return
     */
    public static RouteNode getRoute(String uri) {
        return ROUTE_MAP.get(uri);
    }


    /**
     * 移除某个 路由，禁止访问
     * @param path
     */
    public static void unregister(String path) {
        LOGGER.warn("取消路由{}映射", path);
        ROUTE_MAP.remove(path);

    }

    /**
     * 移除某个Controller类的所有路由
     * @param clazz
     */
    public static void unregister(Class clazz) {
        Set<Map.Entry<String, RouteNode>> set = ROUTE_MAP.entrySet();
        for (Map.Entry<String, RouteNode> item : set) {
            if (item.getValue().getMethod().getDeclaringClass() == clazz) {
                unregister(item.getKey());
            }
        }
    }


    /**
     * 获取一个所有route的遍历器
     * @return
     */
    public static Iterator<RouteNode> getAllRouteIterator() {
        return ROUTE_MAP.values().iterator();
    }

}
